package server

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	jwt "github.com/golangblogs/gojwt"
	"github.com/google/uuid"
	"log"
	"month5/common/model/mysql"
	"month5/common/model/redis"
	"month5/common/proto/user"
	"month5/pkg"
	"strconv"
	"time"
)

func Login(req *user.LoginReq) (*user.LoginResp, error) {
	u := mysql.User{}
	login, err := u.Login(req.Name, req.Password)
	if err != nil {
		return nil, errors.New("登录失败")
	}
	token, err := jwt.NewJWT("zj").CreateToken(jwt.CustomClaims{ID: login.ID})
	if err != nil {
		return nil, errors.New("token生成失败")
	}
	return &user.LoginResp{
		UserId:  int32(login.ID),
		Success: token,
	}, nil
}

func EatList(req *user.EatListReq) (*user.EatListResp, error) {
	t := mysql.Takeout{}
	find, err := t.Find(int(req.Types))
	if err != nil {
		return nil, errors.New("查找失败")
	}

	key := "Takeout:type" + fmt.Sprintf("%d", req.Types)
	var list []*user.EatList
	for _, i := range find {
		list = append(list, &user.EatList{
			Name:  i.Name,
			Price: float32(i.Price),
			Num:   int32(i.Num),
			Types: int32(i.Types),
		})
	}

	marshal, err := json.Marshal(list)
	if err != nil {
		return nil, err
	}
	redis.RDB.LPush(context.Background(), key, marshal)
	redis.RDB.Expire(context.Background(), key, time.Minute*30)

	return &user.EatListResp{List: list}, nil
}

func CreatedOrder(req *user.CreatedOrderReq) (*user.CreatedOrderResp, error) {
	t := mysql.Takeout{}
	Takeouts, err := t.FindId(int(req.TakeoutId))
	if err != nil {
		return nil, errors.New("没有该餐品")
	}
	if Takeouts.Num < int(req.BuyNum) {
		return nil, errors.New(fmt.Sprintf("%s", Takeouts.Name) + "库存不充足不可以下单")
	}

	payPrice := Takeouts.Price * float64(req.BuyNum)

	if req.Coupon == 2 && Takeouts.Types == 1 {
		payPrice = payPrice - 5
	}
	if req.Coupon == 2 && Takeouts.Types == 3 && payPrice >= 199 {
		payPrice = payPrice - 50
	}
	if req.Coupon == 2 && payPrice >= 199 {
		payPrice = payPrice - 50
	}

	OrderSn := uuid.New().String()
	o := mysql.Order{
		UserId:    int(req.UserId),
		TakeoutId: int(req.TakeoutId),
		OrderSn:   OrderSn,
		Name:      Takeouts.Name,
		Price:     Takeouts.Price,
		BuyNum:    int(req.BuyNum),
		PayPrice:  payPrice,
		PayTypes:  int(req.PayTypes),
		Coupon:    int(req.Coupon),
		Notes:     req.Notes,
	}

	err = o.Created()
	if err != nil {
		return nil, errors.New("下单失败")
	}

	key := "oversold:"
	value := Takeouts.Name
	err = redis.RDB.SetNX(context.Background(), key, value, time.Minute*30).Err()
	if err != nil {
		log.Panicln("分布式锁同步失败")
		return nil, err
	}

	defer func() {
		err = redis.RDB.Del(context.Background(), key).Err()
		if err != nil {
			log.Panicln("分布式锁解锁失败")
		}
	}()

	err = t.UpdatedNum(int(req.BuyNum), int(req.TakeoutId))
	if err != nil {
		return nil, errors.New("库存扣减失败")
	}

	amount := strconv.FormatFloat(payPrice, 'f', 2, 64)
	pay := pkg.NewAliPay()
	PayUrl := pay.Pay(Takeouts.Name, OrderSn, amount)

	if o.PayStatus == 3 {
		u := mysql.User{}
		err = u.FindUser(int(req.UserId))
		if err != nil {
			return nil, errors.New("没有该用户")
		}
		err = u.UpdatedUserPoints(int(req.UserId), int(payPrice))
		if err != nil {
			return nil, errors.New("积分发放失败，请前往查看订单是否支付成功")
		}
	}

	return &user.CreatedOrderResp{Success: PayUrl}, nil
}

func PayBack(req *user.PayBackReq) (*user.PayBackResp, error) {
	fmt.Println("支付回调")
	var status int
	if req.Status == "WAIT_BUYER_PAY" {
		status = 1
	} else if req.Status == "TRADE_CLOSED" {
		status = 2
	} else if req.Status == "TRADE_SUCCESS" {
		status = 3
	}

	o := mysql.Order{}
	err := o.UpdatedStatus(req.OrderSn, status)
	if err != nil {
		return nil, errors.New("回调失败")
	}
	return &user.PayBackResp{Success: "回调成功"}, nil
}

func OrderList(req *user.OrderListReq) (*user.OrderListResp, error) {
	o := mysql.Order{}
	orders, err := o.Find()
	if err != nil {
		return nil, err
	}
	var list []*user.OrderList
	for _, order := range orders {
		list = append(list, &user.OrderList{
			UserId:    int32(order.UserId),
			TakeoutId: int32(order.TakeoutId),
			OrderSn:   order.OrderSn,
			Name:      order.Name,
			Price:     float32(order.Price),
			BuyNum:    int32(order.BuyNum),
			PayPrice:  float32(order.PayPrice),
			PayStatus: int32(order.PayStatus),
		})
	}
	return &user.OrderListResp{List: list}, nil
}

func AddCoupon(req *user.AddCouponReq) (*user.AddCouponResp, error) {
	c := mysql.Coupons{}
	find, err := c.Find(int(req.UserId))
	if err != nil {
		return nil, err
	}
	if find.Name != req.Name {
		return nil, errors.New("请不要重复领取这张优惠卷")
	}

	c = mysql.Coupons{
		UserId:        int(req.UserId),
		CouponsPrice:  float64(req.CouponsPrice),
		Name:          req.Name,
		CouponsStatus: int(req.Status),
	}

	err = c.Create()
	if err != nil {
		return nil, errors.New("优惠卷领取失败")
	}
	return &user.AddCouponResp{Success: "优惠卷领取成功"}, nil
}

func LookCoupons(req *user.LookCouponsReq) (*user.LookCouponsResp, error) {
	c := mysql.Coupons{}
	finds, err := c.Finds()
	if err != nil {
		return nil, err
	}
	var list []*user.CouponsList
	for _, find := range finds {
		list = append(list, &user.CouponsList{
			UserId:       int32(find.UserId),
			CouponsPrice: float32(find.CouponsPrice),
			Name:         find.Name,
			Status:       int32(find.CouponsStatus),
		})
	}
	return &user.LookCouponsResp{List: list}, nil
}
